package com.bookrecomm.service.impl;

import com.bookrecomm.dao.CategoryRepository;
import com.bookrecomm.entity.Category;
import com.bookrecomm.service.CategoryService;
import com.bookrecomm.vo.CategoryVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 分类服务实现类
 * 实现分类相关的业务逻辑
 */
@Service
public class CategoryServiceImpl implements CategoryService {

    @Autowired
    private CategoryRepository categoryRepository;

    /**
     * 获取所有分类列表
     * @return 分类列表
     */
    @Override
    public List<CategoryVO> findAll() {
        List<Category> categories = categoryRepository.findAll();
        System.out.println("数据库查询分类结果：" + categories.size() + "条数据");
        
        if (categories.isEmpty()) {
            System.out.println("警告！分类数据为空！请检查数据库");
            // 创建测试分类数据，确保前端至少能显示一些分类
            return createTestCategories();
        }
        
        List<CategoryVO> result = categories.stream()
                .map(this::convertToCategoryVO)
                .collect(Collectors.toList());
                
        System.out.println("返回前端分类数量：" + result.size());
        return result;
    }
    
    /**
     * 创建测试分类数据，当数据库中无数据时使用
     */
    private List<CategoryVO> createTestCategories() {
        System.out.println("创建测试分类数据");
        List<CategoryVO> testData = new ArrayList<>();
        
        CategoryVO fiction = new CategoryVO();
        fiction.setId(1L);
        fiction.setName("小说");
        fiction.setDescription("各类小说书籍");
        fiction.setWeight(100);
        testData.add(fiction);
        
        CategoryVO technology = new CategoryVO();
        technology.setId(2L);
        technology.setName("技术");
        technology.setDescription("计算机和技术相关书籍");
        technology.setWeight(90);
        testData.add(technology);
        
        CategoryVO biography = new CategoryVO();
        biography.setId(3L);
        biography.setName("传记");
        biography.setDescription("名人传记和自传");
        biography.setWeight(80);
        testData.add(biography);
        
        return testData;
    }

    /**
     * 获取原始分类数据(调试用)
     * @return 原始分类数据列表
     */
    @Override
    public List<Category> findRawCategories() {
        List<Category> rawData = categoryRepository.findAll();
        System.out.println("直接从数据库获取分类数据，总数: " + rawData.size());
        
        // 疑难解析: 如果集合为空，尝试查找原因
        if (rawData.isEmpty()) {
            System.out.println("分类表中无数据!尝试查询表是否存在...");
            try {
                // 执行原生查询检查表是否存在
                Boolean tableExists = categoryRepository.existsTable("categories");
                System.out.println("分类表是否存在: " + tableExists);
            } catch (Exception e) {
                System.out.println("检查表时发生异常: " + e.getMessage());
                e.printStackTrace();
            }
        } else {
            // 打印出所有分类数据
            rawData.forEach(c -> {
                System.out.println("分类 ID: " + c.getId() + ", 名称: " + c.getName());
                System.out.println("相关图书数量: " + (c.getBooks() != null ? c.getBooks().size() : "null"));
            });
        }
        
        return rawData;
    }
    
    /**
     * 获取分类树
     * @return 分类树
     */
    @Override
    public List<CategoryVO> findCategoryTree() {
        // 获取所有分类
        List<Category> allCategories = categoryRepository.findAll();
        System.out.println("分类树构建 - 查找到分类数: " + allCategories.size());
        
        // 转换为VO对象
        List<CategoryVO> categoryVOs = allCategories.stream()
                .map(this::convertToCategoryVO)
                .collect(Collectors.toList());
        
        // 按父ID分组
        Map<Long, List<CategoryVO>> categoryMap = categoryVOs.stream()
                .collect(Collectors.groupingBy(
                        category -> category.getParentId() != null ? category.getParentId() : 0L
                ));
        
        // 构建树形结构
        List<CategoryVO> rootCategories = categoryMap.getOrDefault(0L, new ArrayList<>());
        rootCategories.forEach(root -> buildCategoryTree(root, categoryMap));
        
        return rootCategories;
    }

    /**
     * 递归构建分类树
     * @param parent 父分类
     * @param categoryMap 分类映射
     */
    private void buildCategoryTree(CategoryVO parent, Map<Long, List<CategoryVO>> categoryMap) {
        List<CategoryVO> children = categoryMap.getOrDefault(parent.getId(), new ArrayList<>());
        if (!children.isEmpty()) {
            parent.setChildren(children);
            children.forEach(child -> buildCategoryTree(child, categoryMap));
        }
    }

    /**
     * 根据ID查询分类
     * @param id 分类ID
     * @return 分类信息
     */
    @Override
    public CategoryVO findById(Long id) {
        Category category = categoryRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("分类不存在"));
        return convertToCategoryVO(category);
    }

    /**
     * 根据父ID查询子分类
     * @param parentId 父分类ID
     * @return 子分类列表
     */
    @Override
    public List<CategoryVO> findByParentId(Long parentId) {
        List<Category> categories = categoryRepository.findByParentId(parentId);
        return categories.stream()
                .map(this::convertToCategoryVO)
                .collect(Collectors.toList());
    }

    /**
     * 添加分类
     * @param category 分类信息
     * @return 添加后的分类信息
     */
    @Override
    @Transactional
    public CategoryVO addCategory(Category category) {
        // 检查分类名称是否已存在
        if (categoryRepository.existsByName(category.getName())) {
            throw new RuntimeException("分类名称已存在");
        }
        
        // 设置分类层级
        if (category.getParentId() != null) {
            Category parent = categoryRepository.findById(category.getParentId())
                    .orElseThrow(() -> new RuntimeException("父分类不存在"));
            category.setLevel(parent.getLevel() + 1);
        } else {
            category.setLevel(1);
        }
        
        // 设置创建时间和更新时间
        category.setCreatedAt(LocalDateTime.now());
        category.setUpdatedAt(LocalDateTime.now());
        
        // 保存分类
        Category savedCategory = categoryRepository.save(category);
        
        return convertToCategoryVO(savedCategory);
    }

    /**
     * 更新分类
     * @param id 分类ID
     * @param categoryUpdate 分类信息
     * @return 更新后的分类信息
     */
    @Override
    @Transactional
    public CategoryVO updateCategory(Long id, Category categoryUpdate) {
        Category category = categoryRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("分类不存在"));
        
        // 检查分类名称是否已存在
        if (categoryUpdate.getName() != null && !categoryUpdate.getName().equals(category.getName()) && 
                categoryRepository.existsByName(categoryUpdate.getName())) {
            throw new RuntimeException("分类名称已存在");
        }
        
        // 更新分类信息
        if (categoryUpdate.getName() != null) {
            category.setName(categoryUpdate.getName());
        }
        if (categoryUpdate.getDescription() != null) {
            category.setDescription(categoryUpdate.getDescription());
        }
        if (categoryUpdate.getIcon() != null) {
            category.setIcon(categoryUpdate.getIcon());
        }
        if (categoryUpdate.getWeight() != null) {
            category.setWeight(categoryUpdate.getWeight());
        }
        if (categoryUpdate.getStatus() != null) {
            category.setStatus(categoryUpdate.getStatus());
        }
        
        // 更新父分类和层级
        if (categoryUpdate.getParentId() != null && !categoryUpdate.getParentId().equals(category.getParentId())) {
            // 检查是否形成循环引用
            if (categoryUpdate.getParentId().equals(id)) {
                throw new RuntimeException("不能将自己设为父分类");
            }
            
            // 检查是否将父分类设为自己的子分类
            checkCyclicReference(id, categoryUpdate.getParentId());
            
            // 更新父分类和层级
            Category parent = categoryRepository.findById(categoryUpdate.getParentId())
                    .orElseThrow(() -> new RuntimeException("父分类不存在"));
            category.setParentId(categoryUpdate.getParentId());
            category.setLevel(parent.getLevel() + 1);
            
            // 更新子分类的层级
            updateChildrenLevel(category);
        }
        
        // 更新时间
        category.setUpdatedAt(LocalDateTime.now());
        
        // 保存分类
        Category savedCategory = categoryRepository.save(category);
        
        return convertToCategoryVO(savedCategory);
    }

    /**
     * 检查是否形成循环引用
     * @param categoryId 分类ID
     * @param parentId 父分类ID
     */
    private void checkCyclicReference(Long categoryId, Long parentId) {
        if (parentId == null) {
            return;
        }
        
        Category parent = categoryRepository.findById(parentId)
                .orElseThrow(() -> new RuntimeException("父分类不存在"));
        
        if (parent.getParentId() != null) {
            if (parent.getParentId().equals(categoryId)) {
                throw new RuntimeException("不能形成循环引用");
            }
            
            checkCyclicReference(categoryId, parent.getParentId());
        }
    }

    /**
     * 更新子分类的层级
     * @param parent 父分类
     */
    private void updateChildrenLevel(Category parent) {
        List<Category> children = categoryRepository.findByParentId(parent.getId());
        if (!children.isEmpty()) {
            for (Category child : children) {
                child.setLevel(parent.getLevel() + 1);
                child.setUpdatedAt(LocalDateTime.now());
                categoryRepository.save(child);
                
                // 递归更新子分类的层级
                updateChildrenLevel(child);
            }
        }
    }

    /**
     * 删除分类
     * @param id 分类ID
     * @return 是否删除成功
     */
    @Override
    @Transactional
    public boolean deleteCategory(Long id) {
        // 检查分类是否存在
        Category category = categoryRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("分类不存在"));
        
        // 检查是否有子分类
        List<Category> children = categoryRepository.findByParentId(id);
        if (!children.isEmpty()) {
            throw new RuntimeException("该分类下有子分类，不能删除");
        }
        
        // 检查是否有关联的图书
        if (category.getBooks() != null && !category.getBooks().isEmpty()) {
            throw new RuntimeException("该分类下有图书，不能删除");
        }
        
        // 删除分类
        categoryRepository.deleteById(id);
        
        return true;
    }

    /**
     * 将分类实体转换为VO对象
     * @param category 分类实体
     * @return 分类VO对象
     */
    private CategoryVO convertToCategoryVO(Category category) {
        CategoryVO categoryVO = new CategoryVO();
        BeanUtils.copyProperties(category, categoryVO);
        
        try {
            // 强制初始化books集合，避免懒加载问题
            if (category.getBooks() != null) {
                // 第一种方法：缺点是可能会有多一次查询
                int bookCount = category.getBooks().size();
                System.out.println("分类 ID: " + category.getId() + ", 名称: " + category.getName() + ", 图书数量: " + bookCount);
                categoryVO.setBookCount((long) bookCount);
            } else {
                categoryVO.setBookCount(0L);
            }
        } catch (Exception e) {
            // 如果发生异常，记录错误并设置图书数量为0
            System.out.println("获取分类" + category.getId() + "的图书数量时出错: " + e.getMessage());
            categoryVO.setBookCount(0L);
        }
        
        // 记录转换后的数据
        System.out.println("分类VO: id=" + categoryVO.getId() + ", name=" + categoryVO.getName() + ", bookCount=" + categoryVO.getBookCount());
        
        return categoryVO;
    }
}
